Set up

suppressPackageStartupMessages({
  library(tidyverse)
})

Directories and File Inputs/Outputs

# Detect the ".git" folder -- this will be in the project root directory
# Use this as the root directory to ensure proper sourcing of functions 
# no matter where this is called from
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))
analysis_dir <- file.path(root_dir, "analyses", "tmb-vaf-longitudinal")
results_dir <- file.path(analysis_dir, "results")
input_dir <- file.path(analysis_dir, "input")
files_dir <- file.path(root_dir, "analyses", "sample-distribution-analysis", "results")

# Input files
genomic_paired_file <- file.path(files_dir, "list-genomic-paired.tsv") 
tmb_vaf_file <- file.path(results_dir, "tmb_vaf_genomic.tsv")
palette_file <- file.path(root_dir, "figures", "palettes", "oncoprint_color_palette.tsv")

# File path to plot directory
plots_dir <-
  file.path(analysis_dir, "plots")
if (!dir.exists(plots_dir)) {
  dir.create(plots_dir)
}

source(paste0(root_dir, "/figures/scripts/theme.R"))

Read in data and process

tmb_vaf_df <- readr::read_tsv(tmb_vaf_file, guess_max = 100000, show_col_types = FALSE) %>% 
  filter(!tmb >= 10) %>% 
  select(Kids_First_Biospecimen_ID, Variant_Classification, gene_protein, mutation_count,   region_size, tmb, VAF)

genomic_paired_df <- readr::read_tsv(genomic_paired_file, guess_max = 100000, show_col_types = FALSE) %>% 
  left_join(tmb_vaf_df, by = c("Kids_First_Biospecimen_ID"))

# Which patient samples don't have TMB?
#genomic_paired_df %>% 
#  filter(is.na(tmb)) %>% 
#  unique() %>% 
#  regulartable() %>%
#  fontsize(size = 12, part = "all")

# Vector to order timepoints
td_order <- c("Diagnosis", "Progressive", "Recurrence", "Deceased", "Second Malignancy", "Unavailable")

df <- genomic_paired_df %>% 
  filter(!is.na(tmb)) %>% 
  mutate(cgGFAC = case_when(grepl("High-grade glioma", cancer_group) ~ "HGG",
                            grepl("Diffuse midline glioma", cancer_group) ~ "DIPG",
                            grepl("Medulloblastoma", cancer_group) ~ "Medulloblastoma",
                            grepl("Atypical Teratoid Rhabdoid Tumor", cancer_group) ~ "ATRT",
                            grepl("Low-grade glioma", cancer_group) ~ "LGG",
                            grepl("Ependymoma", cancer_group) ~ "Ependymoma",
                            grepl("Chordoma", cancer_group) ~ "Chordoma",
                            TRUE ~ "Other"),
         td_cgGFAC = case_when(grepl("Deceased", tumor_descriptor) ~ "xDeceased",
                                      TRUE ~ tumor_descriptor))


# Let's count #samples per cancer groups and timepoints 
timepoint_cg_n_df <- df %>% 
  count(cancer_group, tumor_descriptor) %>% 
  dplyr::mutate(tumor_descriptor_cg_n = glue::glue("{cancer_group}_{tumor_descriptor}  (N={n})")) %>% 
  dplyr::rename(timepoint_cg_n = n) 

# Let's count #samples per cancer groups and timepoints 
timepoint_cgGFAC_n_df <- df %>% 
  count(cgGFAC, td_cgGFAC) %>% 
  dplyr::mutate(tumor_descriptor_cgGFAC_n = glue::glue("{cgGFAC}_{td_cgGFAC}  (N={n})")) %>% 
  dplyr::rename(timepoint_cgGFAC_n = n) 

# Create df to use for plots
df_plot <- df %>% 
  left_join(timepoint_cg_n_df, by = c("tumor_descriptor", "cancer_group")) %>%
  #filter(!timepoint_n <= 2) 
  left_join(timepoint_cgGFAC_n_df, by = c("td_cgGFAC", "cgGFAC")) %>% 
  mutate(tumor_descriptor = factor(tumor_descriptor),
         tumor_descriptor = fct_relevel(tumor_descriptor, td_order))
        
# Read color palette
palette_df <- readr::read_tsv(palette_file, guess_max = 100000, show_col_types = FALSE) 

# Define and order palette
palette <- palette_df$hex_codes
names(palette) <- palette_df$Variant_Classification
Warning: Unknown or uninitialised column: `Variant_Classification`.
# Define label for plots
Alteration_type <- df_plot$Variant_Classification

# Define ylim
ylim <- max(df_plot$tmb)

What type of alterations we observe per tumor descriptor?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        scale_y_continuous(limits = c(0, ylim)) +
        ylab("TMB") +
        xlab("Timepoint") +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_timepoints.pdf", 
       path = plots_dir, 
       width = 15, 
       height = 8, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cancer_group) +
        theme_Publication() + 
        ylab("TMB") +
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_cancer_group.pdf", 
       path = plots_dir, 
       width = 25, 
       height = 18, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group defined by cgGFAC?

df_plot_cgGFAC <- df_plot %>% 
  arrange(tumor_descriptor_cgGFAC_n)
  #mutate(tumor_descriptor_cgGFAC_n = factor(tumor_descriptor_cgGFAC_n)) 

#df_plot_cgGFAC$tumor_descriptor_cgGFAC_n %>% levels()

# Create bxp
print(ggpubr::ggboxplot(df_plot_cgGFAC, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        #facet_wrap(~cgGFAC) +
        theme_Publication() + 
        ylab("TMB") +
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))


# Save the plot
ggsave(filename = "Alteration_type_cgGFAC.pdf", 
       path = plots_dir, 
       width = 18, 
       height = 12, 
       device = "pdf", 
       useDingbats = FALSE)
cgGFAC_id <- as.character(unique(df_plot_cgGFAC$cgGFAC))
cgGFAC_id
[1] "ATRT"            "Chordoma"        "DIPG"            "Ependymoma"      "HGG"             "LGG"             "Medulloblastoma"
[8] "Other"          
# Loop through variable
for (i in seq_along(cgGFAC_id)){
  print(i)
  df_sub <- df_plot_cgGFAC %>%
      filter(cgGFAC == cgGFAC_id[i])

  
   # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        ylab("TMB") +
        labs(title = paste(cg)) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8

What type of alterations we observe per tumor descriptor in each cancer group (add _n))?

cg <- as.character(unique(df_plot$cancer_group))
cg
 [1] "CNS Embryonal tumor"                       "Embryonal tumor with multilayer rosettes"  "Low-grade glioma"                         
 [4] "Ependymoma"                                "Medulloblastoma"                           "Atypical Teratoid Rhabdoid Tumor"         
 [7] "Diffuse midline glioma"                    "High-grade glioma"                         "Ganglioglioma"                            
[10] NA                                          "Meningioma"                                "Glial-neuronal tumor"                     
[13] "Pilocytic astrocytoma"                     "Neuroblastoma"                             "Ganglioneuroblastoma"                     
[16] "Schwannoma"                                "Chordoma"                                  "Fibromyxoid lesion"                       
[19] "Neurofibroma/Plexiform"                    "Malignant peripheral nerve sheath tumor"   "Choroid plexus carcinoma"                 
[22] "Adamantinomatous Craniopharyngioma"        "Dysembryoplastic neuroepithelial tumor"    "Ewing sarcoma"                            
[25] "Rosai-Dorfman disease"                     "Hemangioblastoma"                          "Craniopharyngioma"                        
[28] "Diffuse leptomeningeal glioneuronal tumor"
# Loop through variable
for (i in seq_along(cg)){
  print(i)
  df_sub <- df_plot %>%
      filter(cancer_group == cg[i])
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cg_n", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        ylab("TMB") +
        xlab("Timepoint") +
        labs(title = paste(cg)) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))

  # Save the plot
  #name <- paste0(cg[i], "-Alteration_type_cancer_group.pdf")
  #ggsave(filename = name, 
  #       path = plots_dir, 
  #       width = 12, 
  #       height = 8, 
  #       device = "pdf", 
  #       useDingbats = FALSE)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
[1] 21
[1] 22
[1] 23
[1] 24
[1] 25
[1] 26
[1] 27
[1] 28

What type of alterations we observe per tumor descriptor in each cancer group and timepoint model?

tm <- as.character(unique(df_plot$timepoints_models))
tm
 [1] "Dx-Rec"         "Dx-Pro"         "Dx-Dec"         "Pro-Dec"        "Rec-SM"         "Pro-Rec"        "Dx-SM"          "Pro-Rec-Dec"   
 [9] "Dx-Pro-Rec"     "Rec-Dec"        "Dx-Pro-Rec-Dec" "Dx-Rec-Dec"     "Dx-Pro-Dec"     "Dx-Unv"        
# Loop through variable
for (i in seq_along(tm)){
  print(i)
  df_sub <- df_plot %>%
      filter(timepoints_models == tm[i])
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cancer_group) +
        theme_Publication() +
        ylab("TMB") +
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))

   # Save the plot
   #name <- paste0(timepoints_models[i], "-Alteration_type_cancer_group.pdf")
   #ggsave(filename = name, 
   #    path = plots_dir, 
   #    width = 12, 
   #    height = 8, 
   #   device = "pdf", 
   #   useDingbats = FALSE)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14

sessionInfo()
R version 4.2.3 (2023-03-15)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.5.1

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] ggthemes_4.2.4  lubridate_1.9.2 forcats_1.0.0   stringr_1.5.0   dplyr_1.1.2     purrr_1.0.1     readr_2.1.4     tidyr_1.3.0    
 [9] tibble_3.2.1    ggplot2_3.4.2   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] bslib_0.5.0       tidyselect_1.2.0  xfun_0.39         carData_3.0-5     colorspace_2.1-0  vctrs_0.6.3       generics_0.1.3   
 [8] htmltools_0.5.5   yaml_2.3.7        utf8_1.2.3        rlang_1.1.1       jquerylib_0.1.4   ggpubr_0.6.0      pillar_1.9.0     
[15] glue_1.6.2        withr_2.5.0       bit64_4.0.5       lifecycle_1.0.3   munsell_0.5.0     ggsignif_0.6.4    gtable_0.3.3     
[22] ragg_1.2.5        evaluate_0.21     labeling_0.4.2    knitr_1.43        tzdb_0.4.0        fastmap_1.1.1     parallel_4.2.3   
[29] fansi_1.0.4       broom_1.0.5       scales_1.2.1      backports_1.4.1   cachem_1.0.8      vroom_1.6.3       jsonlite_1.8.7   
[36] abind_1.4-5       systemfonts_1.0.4 farver_2.1.1      bit_4.0.5         textshaping_0.3.6 hms_1.1.3         digest_0.6.33    
[43] stringi_1.7.12    rstatix_0.7.2     rprojroot_2.0.3   cli_3.6.1         tools_4.2.3       sass_0.4.7        magrittr_2.0.3   
[50] crayon_1.5.2      car_3.1-2         pkgconfig_2.0.3   timechange_0.2.0  rmarkdown_2.23    rstudioapi_0.15.0 R6_2.5.1         
[57] compiler_4.2.3   
LS0tCnRpdGxlOiAiQ2xhc3NpZmljYXRpb24gb2YgVmFyaWFudHMgYWNyb3NzIHBhaXJlZCBsb25naXR1ZGluYWwgc2FtcGxlcyBpbiB0aGUgUEJUQSBDb2hvcnQiCmF1dGhvcjogJ0FudG9uaWEgQ2hyb25pIDxjaHJvbmlhQGNob3AuZWR1PiBhbmQgSm8gTHlubmUgUm9raXRhIDxyb2tpdGFAY2hvcC5lZHU+IGZvciBEM0InCmRhdGU6ICIyMDIzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCi0tLQoKIyBTZXQgdXAKYGBge3IgbG9hZC1saWJyYXJ5fQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewogIGxpYnJhcnkodGlkeXZlcnNlKQp9KQpgYGAKCiMjIERpcmVjdG9yaWVzIGFuZCBGaWxlIElucHV0cy9PdXRwdXRzCmBgYHtyIHNldC1kaXItYW5kLWZpbGUtbmFtZXN9CiMgRGV0ZWN0IHRoZSAiLmdpdCIgZm9sZGVyIC0tIHRoaXMgd2lsbCBiZSBpbiB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeQojIFVzZSB0aGlzIGFzIHRoZSByb290IGRpcmVjdG9yeSB0byBlbnN1cmUgcHJvcGVyIHNvdXJjaW5nIG9mIGZ1bmN0aW9ucyAKIyBubyBtYXR0ZXIgd2hlcmUgdGhpcyBpcyBjYWxsZWQgZnJvbQpyb290X2RpciA8LSBycHJvanJvb3Q6OmZpbmRfcm9vdChycHJvanJvb3Q6Omhhc19kaXIoIi5naXQiKSkKYW5hbHlzaXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInRtYi12YWYtbG9uZ2l0dWRpbmFsIikKcmVzdWx0c19kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgInJlc3VsdHMiKQppbnB1dF9kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgImlucHV0IikKZmlsZXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInNhbXBsZS1kaXN0cmlidXRpb24tYW5hbHlzaXMiLCAicmVzdWx0cyIpCgojIElucHV0IGZpbGVzCmdlbm9taWNfcGFpcmVkX2ZpbGUgPC0gZmlsZS5wYXRoKGZpbGVzX2RpciwgImxpc3QtZ2Vub21pYy1wYWlyZWQudHN2IikgCnRtYl92YWZfZmlsZSA8LSBmaWxlLnBhdGgocmVzdWx0c19kaXIsICJ0bWJfdmFmX2dlbm9taWMudHN2IikKcGFsZXR0ZV9maWxlIDwtIGZpbGUucGF0aChyb290X2RpciwgImZpZ3VyZXMiLCAicGFsZXR0ZXMiLCAib25jb3ByaW50X2NvbG9yX3BhbGV0dGUudHN2IikKCiMgRmlsZSBwYXRoIHRvIHBsb3QgZGlyZWN0b3J5CnBsb3RzX2RpciA8LQogIGZpbGUucGF0aChhbmFseXNpc19kaXIsICJwbG90cyIpCmlmICghZGlyLmV4aXN0cyhwbG90c19kaXIpKSB7CiAgZGlyLmNyZWF0ZShwbG90c19kaXIpCn0KCnNvdXJjZShwYXN0ZTAocm9vdF9kaXIsICIvZmlndXJlcy9zY3JpcHRzL3RoZW1lLlIiKSkKYGBgCgojIyBSZWFkIGluIGRhdGEgYW5kIHByb2Nlc3MKYGBge3IgbG9hZC1wcm9jZXNzLWlucHV0c30KdG1iX3ZhZl9kZiA8LSByZWFkcjo6cmVhZF90c3YodG1iX3ZhZl9maWxlLCBndWVzc19tYXggPSAxMDAwMDAsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JSAKICBmaWx0ZXIoIXRtYiA+PSAxMCkgJT4lIAogIHNlbGVjdChLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lELCBWYXJpYW50X0NsYXNzaWZpY2F0aW9uLCBnZW5lX3Byb3RlaW4sIG11dGF0aW9uX2NvdW50LAlyZWdpb25fc2l6ZSwgdG1iLCBWQUYpCgpnZW5vbWljX3BhaXJlZF9kZiA8LSByZWFkcjo6cmVhZF90c3YoZ2Vub21pY19wYWlyZWRfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUgCiAgbGVmdF9qb2luKHRtYl92YWZfZGYsIGJ5ID0gYygiS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRCIpKQoKIyBXaGljaCBwYXRpZW50IHNhbXBsZXMgZG9uJ3QgaGF2ZSBUTUI/CiNnZW5vbWljX3BhaXJlZF9kZiAlPiUgCiMgIGZpbHRlcihpcy5uYSh0bWIpKSAlPiUgCiMgIHVuaXF1ZSgpICU+JSAKIyAgcmVndWxhcnRhYmxlKCkgJT4lCiMgIGZvbnRzaXplKHNpemUgPSAxMiwgcGFydCA9ICJhbGwiKQoKIyBWZWN0b3IgdG8gb3JkZXIgdGltZXBvaW50cwp0ZF9vcmRlciA8LSBjKCJEaWFnbm9zaXMiLCAiUHJvZ3Jlc3NpdmUiLCAiUmVjdXJyZW5jZSIsICJEZWNlYXNlZCIsICJTZWNvbmQgTWFsaWduYW5jeSIsICJVbmF2YWlsYWJsZSIpCgpkZiA8LSBnZW5vbWljX3BhaXJlZF9kZiAlPiUgCiAgZmlsdGVyKCFpcy5uYSh0bWIpKSAlPiUgCiAgbXV0YXRlKGNnR0ZBQyA9IGNhc2Vfd2hlbihncmVwbCgiSGlnaC1ncmFkZSBnbGlvbWEiLCBjYW5jZXJfZ3JvdXApIH4gIkhHRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiRGlmZnVzZSBtaWRsaW5lIGdsaW9tYSIsIGNhbmNlcl9ncm91cCkgfiAiRElQRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiTWVkdWxsb2JsYXN0b21hIiwgY2FuY2VyX2dyb3VwKSB+ICJNZWR1bGxvYmxhc3RvbWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIkF0eXBpY2FsIFRlcmF0b2lkIFJoYWJkb2lkIFR1bW9yIiwgY2FuY2VyX2dyb3VwKSB+ICJBVFJUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJMb3ctZ3JhZGUgZ2xpb21hIiwgY2FuY2VyX2dyb3VwKSB+ICJMR0ciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIkVwZW5keW1vbWEiLCBjYW5jZXJfZ3JvdXApIH4gIkVwZW5keW1vbWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIkNob3Jkb21hIiwgY2FuY2VyX2dyb3VwKSB+ICJDaG9yZG9tYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk90aGVyIiksCiAgICAgICAgIHRkX2NnR0ZBQyA9IGNhc2Vfd2hlbihncmVwbCgiRGVjZWFzZWQiLCB0dW1vcl9kZXNjcmlwdG9yKSB+ICJ4RGVjZWFzZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiB0dW1vcl9kZXNjcmlwdG9yKSkKCgojIExldCdzIGNvdW50ICNzYW1wbGVzIHBlciBjYW5jZXIgZ3JvdXBzIGFuZCB0aW1lcG9pbnRzIAp0aW1lcG9pbnRfY2dfbl9kZiA8LSBkZiAlPiUgCiAgY291bnQoY2FuY2VyX2dyb3VwLCB0dW1vcl9kZXNjcmlwdG9yKSAlPiUgCiAgZHBseXI6Om11dGF0ZSh0dW1vcl9kZXNjcmlwdG9yX2NnX24gPSBnbHVlOjpnbHVlKCJ7Y2FuY2VyX2dyb3VwfV97dHVtb3JfZGVzY3JpcHRvcn0gIChOPXtufSkiKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUodGltZXBvaW50X2NnX24gPSBuKSAKCiMgTGV0J3MgY291bnQgI3NhbXBsZXMgcGVyIGNhbmNlciBncm91cHMgYW5kIHRpbWVwb2ludHMgCnRpbWVwb2ludF9jZ0dGQUNfbl9kZiA8LSBkZiAlPiUgCiAgY291bnQoY2dHRkFDLCB0ZF9jZ0dGQUMpICU+JSAKICBkcGx5cjo6bXV0YXRlKHR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24gPSBnbHVlOjpnbHVlKCJ7Y2dHRkFDfV97dGRfY2dHRkFDfSAgKE49e259KSIpKSAlPiUgCiAgZHBseXI6OnJlbmFtZSh0aW1lcG9pbnRfY2dHRkFDX24gPSBuKSAKCiMgQ3JlYXRlIGRmIHRvIHVzZSBmb3IgcGxvdHMKZGZfcGxvdCA8LSBkZiAlPiUgCiAgbGVmdF9qb2luKHRpbWVwb2ludF9jZ19uX2RmLCBieSA9IGMoInR1bW9yX2Rlc2NyaXB0b3IiLCAiY2FuY2VyX2dyb3VwIikpICU+JQogICNmaWx0ZXIoIXRpbWVwb2ludF9uIDw9IDIpIAogIGxlZnRfam9pbih0aW1lcG9pbnRfY2dHRkFDX25fZGYsIGJ5ID0gYygidGRfY2dHRkFDIiwgImNnR0ZBQyIpKSAlPiUgCiAgbXV0YXRlKHR1bW9yX2Rlc2NyaXB0b3IgPSBmYWN0b3IodHVtb3JfZGVzY3JpcHRvciksCiAgICAgICAgIHR1bW9yX2Rlc2NyaXB0b3IgPSBmY3RfcmVsZXZlbCh0dW1vcl9kZXNjcmlwdG9yLCB0ZF9vcmRlcikpCiAgICAgICAgCmBgYCAKCgpgYGB7ciBkZWZpbmUtcGFyYW1ldGVycy1mb3ItcGxvdHN9CiMgUmVhZCBjb2xvciBwYWxldHRlCnBhbGV0dGVfZGYgPC0gcmVhZHI6OnJlYWRfdHN2KHBhbGV0dGVfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAKCiMgRGVmaW5lIGFuZCBvcmRlciBwYWxldHRlCnBhbGV0dGUgPC0gcGFsZXR0ZV9kZiRoZXhfY29kZXMKbmFtZXMocGFsZXR0ZSkgPC0gcGFsZXR0ZV9kZiRWYXJpYW50X0NsYXNzaWZpY2F0aW9uCgojIERlZmluZSBsYWJlbCBmb3IgcGxvdHMKQWx0ZXJhdGlvbl90eXBlIDwtIGRmX3Bsb3QkVmFyaWFudF9DbGFzc2lmaWNhdGlvbgoKIyBEZWZpbmUgeWxpbQp5bGltIDwtIG1heChkZl9wbG90JHRtYikKYGBgCgojIFdoYXQgdHlwZSBvZiBhbHRlcmF0aW9ucyB3ZSBvYnNlcnZlIHBlciB0dW1vciBkZXNjcmlwdG9yPwoKYGBge3IgcGxvdC10aW1lcG9pbnQsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CiMgQ3JlYXRlIGJ4cApwcmludChnZ3B1YnI6OmdnYm94cGxvdChkZl9wbG90LCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHlsYWIoIlRNQiIpICsKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpKQoKIyBTYXZlIHRoZSBwbG90Cmdnc2F2ZShmaWxlbmFtZSA9ICJBbHRlcmF0aW9uX3R5cGVfdGltZXBvaW50cy5wZGYiLCAKICAgICAgIHBhdGggPSBwbG90c19kaXIsIAogICAgICAgd2lkdGggPSAxNSwgCiAgICAgICBoZWlnaHQgPSA4LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXA/CgpgYGB7ciBwbG90LWNhbmNlci1ncm91cCwgZmlnLndpZHRoID0gMjUsIGZpZy5oZWlnaHQgPSAxOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CiMgQ3JlYXRlIGJ4cApwcmludChnZ3B1YnI6OmdnYm94cGxvdChkZl9wbG90LCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmNhbmNlcl9ncm91cCkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICB5bGFiKCJUTUIiKSArCiAgICAgICAgeGxhYigiVGltZXBvaW50IikgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIHlsaW0pKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpKQoKIyBTYXZlIHRoZSBwbG90Cmdnc2F2ZShmaWxlbmFtZSA9ICJBbHRlcmF0aW9uX3R5cGVfY2FuY2VyX2dyb3VwLnBkZiIsIAogICAgICAgcGF0aCA9IHBsb3RzX2RpciwgCiAgICAgICB3aWR0aCA9IDI1LCAKICAgICAgIGhlaWdodCA9IDE4LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgZGVmaW5lZCBieSBjZ0dGQUM/CgpgYGB7ciBwbG90LWNnR0ZBQy1uLCBmaWcud2lkdGggPSAxOCwgZmlnLmhlaWdodCA9IDEyLCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KZGZfcGxvdF9jZ0dGQUMgPC0gZGZfcGxvdCAlPiUgCiAgYXJyYW5nZSh0dW1vcl9kZXNjcmlwdG9yX2NnR0ZBQ19uKQogICNtdXRhdGUodHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiA9IGZhY3Rvcih0dW1vcl9kZXNjcmlwdG9yX2NnR0ZBQ19uKSkgCgojZGZfcGxvdF9jZ0dGQUMkdHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiAlPiUgbGV2ZWxzKCkKCiMgQ3JlYXRlIGJ4cApwcmludChnZ3B1YnI6OmdnYm94cGxvdChkZl9wbG90X2NnR0ZBQywgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiIsIAogICAgICAgICAgICAgICAgICAgICAgICB5ID0gInRtYiIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJWYXJpYW50X0NsYXNzaWZpY2F0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IHBhbGV0dGUpICsKICAgICAgICAjZmFjZXRfd3JhcCh+Y2dHRkFDKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHlsYWIoIlRNQiIpICsKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgeWxpbSkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkpCgojIFNhdmUgdGhlIHBsb3QKZ2dzYXZlKGZpbGVuYW1lID0gIkFsdGVyYXRpb25fdHlwZV9jZ0dGQUMucGRmIiwgCiAgICAgICBwYXRoID0gcGxvdHNfZGlyLCAKICAgICAgIHdpZHRoID0gMTgsIAogICAgICAgaGVpZ2h0ID0gMTIsIAogICAgICAgZGV2aWNlID0gInBkZiIsIAogICAgICAgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmBgYAoKCmBgYHtyIHBsb3QtY2dHRkFDLW4taW5kaXZpZHVhbC1wbG90cywgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQpjZ0dGQUNfaWQgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9wbG90X2NnR0ZBQyRjZ0dGQUMpKQpjZ0dGQUNfaWQKCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcoY2dHRkFDX2lkKSl7CiAgcHJpbnQoaSkKICBkZl9zdWIgPC0gZGZfcGxvdF9jZ0dGQUMgJT4lCiAgICAgIGZpbHRlcihjZ0dGQUMgPT0gY2dHRkFDX2lkW2ldKQoKICAKICAgIyBDcmVhdGUgYnhwCiAgcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfc3ViLCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yX2NnR0ZBQ19uIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICB5bGFiKCJUTUIiKSArCiAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKGNnKSkgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIHlsaW0pKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMSkpKQp9CmBgYAoKIyBXaGF0IHR5cGUgb2YgYWx0ZXJhdGlvbnMgd2Ugb2JzZXJ2ZSBwZXIgdHVtb3IgZGVzY3JpcHRvciBpbiBlYWNoIGNhbmNlciBncm91cCAoYWRkIF9uKSk/CiAKCmBgYHtyIHBsb3QtbiwgZmlnLndpZHRoID0gOCwgZmlnLmhlaWdodCA9IDYsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQpjZyA8LSBhcy5jaGFyYWN0ZXIodW5pcXVlKGRmX3Bsb3QkY2FuY2VyX2dyb3VwKSkKY2cKCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcoY2cpKXsKICBwcmludChpKQogIGRmX3N1YiA8LSBkZl9wbG90ICU+JQogICAgICBmaWx0ZXIoY2FuY2VyX2dyb3VwID09IGNnW2ldKQogIAogICMgQ3JlYXRlIGJ4cAogIHByaW50KGdncHVicjo6Z2dib3hwbG90KGRmX3N1YiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvcl9jZ19uIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICB5bGFiKCJUTUIiKSArCiAgICAgICAgeGxhYigiVGltZXBvaW50IikgKwogICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZShjZykpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdCA9IDEpKSkKCiAgIyBTYXZlIHRoZSBwbG90CiAgI25hbWUgPC0gcGFzdGUwKGNnW2ldLCAiLUFsdGVyYXRpb25fdHlwZV9jYW5jZXJfZ3JvdXAucGRmIikKICAjZ2dzYXZlKGZpbGVuYW1lID0gbmFtZSwgCiAgIyAgICAgICBwYXRoID0gcGxvdHNfZGlyLCAKICAjICAgICAgIHdpZHRoID0gMTIsIAogICMgICAgICAgaGVpZ2h0ID0gOCwgCiAgIyAgICAgICBkZXZpY2UgPSAicGRmIiwgCiAgIyAgICAgICB1c2VEaW5nYmF0cyA9IEZBTFNFKQp9CmBgYAoKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgYW5kIHRpbWVwb2ludCBtb2RlbD8KCmBgYHtyIHBsb3QtdGltZXBvaW50LW1vZGVsLCBmaWcud2lkdGggPSAyNSwgZmlnLmhlaWdodCA9IDE4LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KdG0gPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9wbG90JHRpbWVwb2ludHNfbW9kZWxzKSkKdG0KCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcodG0pKXsKICBwcmludChpKQogIGRmX3N1YiA8LSBkZl9wbG90ICU+JQogICAgICBmaWx0ZXIodGltZXBvaW50c19tb2RlbHMgPT0gdG1baV0pCiAgCiAgIyBDcmVhdGUgYnhwCiAgcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfc3ViLCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmNhbmNlcl9ncm91cCkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKwogICAgICAgIHlsYWIoIlRNQiIpICsKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgeWxpbSkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkpCgogICAjIFNhdmUgdGhlIHBsb3QKICAgI25hbWUgPC0gcGFzdGUwKHRpbWVwb2ludHNfbW9kZWxzW2ldLCAiLUFsdGVyYXRpb25fdHlwZV9jYW5jZXJfZ3JvdXAucGRmIikKICAgI2dnc2F2ZShmaWxlbmFtZSA9IG5hbWUsIAogICAjICAgIHBhdGggPSBwbG90c19kaXIsIAogICAjICAgIHdpZHRoID0gMTIsIAogICAjICAgIGhlaWdodCA9IDgsIAogICAjICAgZGV2aWNlID0gInBkZiIsIAogICAjICAgdXNlRGluZ2JhdHMgPSBGQUxTRSkKfQpgYGAKCgpgYGB7ciBlY2hvPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBgCg==